using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

namespace Framework.Fsm
{
    public class FsmStateNode : StackNode
    {
        private static int _id = 1;
        public FsmUserData Data { get; private set; }
        public string Name { get { return title_label.text; } }
        public List<FsmEventItem> EventList = new List<FsmEventItem>();
        private FsmGraphContext _context;
        private TextField title_input;
        private Label title_label;
        private VisualElement _eventContainer;
        private Port inputPort;
        public FsmStateNode()
        {
            Data = new FsmUserData() { Id = Guid.NewGuid().ToString(), DataType = UserDataType.State, Target = this };
            title_label = new Label("state" + (_id++));
            headerContainer.Add(title_label);
            title_input = new TextField();
            headerContainer.Add(title_input);


            setupRenamableTitle();
            inputPort = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, typeof(Port));
            inputPort.userData = Data;
            inputPort.portName = "";
            inputContainer.Add(inputPort);
            inputPort.SetPosition(new Rect(new Vector2(-10, 51), new Vector2(50, 50)));

            var toolbar = new Toolbar();

            toolbar.Add(new Button(() =>
            {
                AddEvent();

            })
            { text = "添加事件" });
            // toolbar.Add(new Button(() =>
            // {
            //     var pos = this.ChangeCoordinatesTo(this, this.GetPosition().position);
            //     onAddAction(pos);
            // })
            // { text = "添加行为" });

            headerContainer.Add(toolbar);
            _eventContainer = new VisualElement();
            // addEvent();
            hierarchy.Insert(2, _eventContainer);
            hierarchy.Insert(3, new Label("行为"));

        }
        public void SetName(string value)
        {
            title_label.text = value;
        }
        public void AddAction(string type, string name)
        {
            onActionSelect(FsmProvider.GetTypeByName(type), name);
        }
        public void AddAction(FsmDataActionData value)
        {
            var action = new FsmActionItem();
            action.Node = this;
            action.Initialize(_context);
            action.Set(value);
            AddElement(action);
        }
        public Edge ConnectTo(FsmEventItem e)
        {
            return inputPort.ConnectTo(e.Port);
        }
        public Edge ConnectTo(FsmEntryPointNode e)
        {
            return inputPort.ConnectTo(e.outputPort);
        }
        void setupRenamableTitle()
        {
            title_input.style.display = DisplayStyle.None;
            title_label.RegisterCallback<MouseDownEvent>(e =>
            {
                if (e.clickCount == 2 && e.button == (int)MouseButton.LeftMouse)
                {
                    title_input.value = title_label.text;
                    title_input.style.display = DisplayStyle.Flex;
                    title_label.style.display = DisplayStyle.None;
                    title_input.focusable = true;

                    title_input.SetValueWithoutNotify(title);
                    title_input.Focus();
                    title_input.SelectAll();
                    title_input.value = title_label.text;
                }
            });
            title_input.RegisterCallback<FocusOutEvent>(e =>
            {
                title_input.style.display = DisplayStyle.None;
                title_label.style.display = DisplayStyle.Flex;
                title_input.focusable = false;
                var newTitle = title_input.value;
                if (string.IsNullOrEmpty(newTitle))
                {
                    newTitle = this.title_label.text;
                }
                this.title_label.text = newTitle.Trim();
            });
            title_input.RegisterCallback<KeyDownEvent>(e =>
            {
                if (e.keyCode == KeyCode.KeypadEnter || e.keyCode == KeyCode.Return)
                {
                    title_input.style.display = DisplayStyle.None;
                    title_label.style.display = DisplayStyle.Flex;
                    var newTitle = title_input.value;
                    if (string.IsNullOrEmpty(newTitle))
                    {
                        newTitle = this.title_label.text;
                    }
                    this.title_label.text = newTitle.Trim();
                }
            });
        }
        public void Initialize(FsmGraphContext context)
        {
            _context = context;
            this.SetPosition(new Rect(_context.NodePosition, new Vector2(100, 100)));
        }
        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
        {
            base.BuildContextualMenu(evt);
            evt.menu.InsertAction(0, "修改标题", (e) =>
           {
               title_input.value = title_label.text;
               title_input.style.display = DisplayStyle.Flex;
               title_label.style.display = DisplayStyle.None;
               title_input.focusable = true;

               title_input.SetValueWithoutNotify(title);
               title_input.Focus();
               title_input.SelectAll();
               title_input.value = title_label.text;
           }, DropdownMenuAction.AlwaysEnabled);
            evt.menu.InsertAction(0, "添加行为", (e) =>
            {
                onAddAction(evt.localMousePosition + new Vector2(120, 60));
            }, DropdownMenuAction.AlwaysEnabled);

        }
        private void onAddAction(Vector2 pos)
        {
            _context.ActionSearchProvider.OnSelect = onActionSelect;
            Vector2 position = this.ChangeCoordinatesTo(_context.View.contentContainer, pos);
            SearchWindow.Open(new SearchWindowContext(position + EditorWindow.focusedWindow.position.position), _context.ActionSearchProvider);
        }
        private FsmActionItem addAction(Type type, string name)
        {
            var action = new FsmActionItem();
            action.Node = this;
            action.Initialize(_context);
            action.Set(type, name);
            AddElement(action);
            return action;
        }
        private void onActionSelect(Type type, string name)
        {
            if (type == null) return;
            AddElement(addAction(type, name));
        }
        protected override bool AcceptsElement(GraphElement element, ref int proposedIndex, int maxIndex)
        {

            bool accept = base.AcceptsElement(element, ref proposedIndex, maxIndex);

            if (accept && element is FsmActionItem item)
            {
                // addid
                item.Node = this;
                return true;
            }

            return false;
        }

        public override bool DragLeave(DragLeaveEvent evt, IEnumerable<ISelectable> selection, IDropTarget leftTarget, ISelection dragSource)
        {
            foreach (var elem in selection)
            {
                if (elem is FsmActionItem item)
                {
                    // removeid
                    item.Node = null;
                }
            }
            return base.DragLeave(evt, selection, leftTarget, dragSource);
        }
        public FsmEventItem AddEvent()
        {
            var e = new FsmEventItem(this);
            EventList.Add(e);
            _eventContainer.Add(e);
            onEventNameChanged(null);
            return e;
        }
        public void RemoveEvent(FsmEventItem item)
        {
            _eventContainer.Remove(item);
            EventList.Remove(item);
            onEventNameChanged(null);
            _context.View.RemovePort(item.Port);
            this.RefreshPorts();
        }
        public void onEventNameChanged(FsmEventItem item)
        {
            Dictionary<string, int> _error = new Dictionary<string, int>();
            List<FsmEventItem> list = new List<FsmEventItem>();
            foreach (var c in _eventContainer.Children())
            {
                var e = c as FsmEventItem;
                if (e == null) continue;
                list.Add(e);
                if (_error.TryGetValue(e.EventName, out int count))
                {
                    _error[e.EventName] = count + 1;
                }
                else
                {
                    _error.Add(e.EventName, 1);
                }
            }
            foreach (var e in list)
            {
                e.SetError(_error[e.EventName] > 1);
            }
        }
        public List<FsmActionItem> GetActionItems()
        {
            List<FsmActionItem> list = new List<FsmActionItem>();

            foreach (var item in this.contentContainer.Children())
            {
                if (item is FsmActionItem action)
                {
                    list.Add(action);
                }
            }
            return list;
        }
        public void MouseDownCallback(MouseDownEvent e)
        {
            if (e.button == 0)
            {
                foreach (var item in this.contentContainer.Children())
                {
                    if (item is FsmActionItem action)
                    {
                        action.CloseSettings();
                    }
                }
            }
        }
    }
}